﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Haidou.Wpf.Util.Extensions
{
	/// <summary>
	/// 图像扩展
	/// </summary>
	public static class ImageExtensions
	{
		/// <summary>
		/// 从源获取BitmapSource并关闭文件使用。
		/// </summary>
		/// <param name="fileSource">The file to open.</param>
		/// <param name="size">The maximum height of the image.</param>
		/// <returns>The open BitmapSource.</returns>
		public static BitmapSource SourceFrom(this string fileSource, int? size = null)
		{
			using (FileStream stream = new(fileSource, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
			{
				BitmapImage bitmapImage = new();
				bitmapImage.BeginInit();
				bitmapImage.CacheOption = BitmapCacheOption.OnLoad;

				if (size.HasValue)
				{
					bitmapImage.DecodePixelHeight = size.Value;
				}

				bitmapImage.StreamSource = stream;
				bitmapImage.EndInit();
				bitmapImage.Freeze(); //使当前对象不可修改并设置其系统。Windows.Freezable.IsFrozen
									  //属性设置为true。Just in case you want to load the image in another thread  以防万一您想在另一个线程中加载图像
				return bitmapImage;
			}
		}

		/// <summary>
		/// 从源获取BitmapSource并关闭文件使用。
		/// </summary>
		/// <param name="array">The array to open.</param>
		/// <param name="size">The maximum height of the image.</param>
		/// <returns>The open BitmapSource.</returns>
		public static BitmapSource SourceFrom(this byte[] array, int? size = null)
		{
			using (MemoryStream stream = new(array))
			{
				BitmapImage bitmapImage = new();
				bitmapImage.BeginInit();
				bitmapImage.CacheOption = BitmapCacheOption.OnLoad;

				if (size.HasValue)
				{
					bitmapImage.DecodePixelHeight = size.Value;
				}

				bitmapImage.StreamSource = stream;
				bitmapImage.EndInit();
				bitmapImage.Freeze(); //Just in case you want to load the image in another thread
				return bitmapImage;
			}
		}

		/// <summary>
		/// 从源获取BitmapSource并关闭文件使用。
		/// </summary>
		/// <param name="stream">The stream to open.</param>
		/// <param name="size">The maximum height of the image.</param>
		/// <returns>The open BitmapSource.</returns>
		public static BitmapSource SourceFrom(this Stream stream, int? size = null)
		{
			BitmapImage bitmapImage = new();
			bitmapImage.BeginInit();
			bitmapImage.CacheOption = BitmapCacheOption.OnLoad;

			if (size.HasValue)
			{
				bitmapImage.DecodePixelHeight = size.Value;
			}

			bitmapImage.StreamSource = stream;
			bitmapImage.EndInit();
			bitmapImage.Freeze(); //Just in case you want to load the image in another thread
			return bitmapImage;
		}

		/// <summary>
		/// 从源获取BitmapSource并关闭文件使用。
		/// </summary>
		/// <param name="fileSource">The file to open.</param>
		/// <param name="rect">The desired crop area.</param>
		/// <returns>The open BitmapSource.</returns>
		public static BitmapSource CropFrom(this string fileSource, Int32Rect rect)
		{
			using (FileStream stream = new(fileSource, FileMode.Open, FileAccess.Read))
			{
				BitmapImage bitmapImage = new();
				bitmapImage.BeginInit();
				bitmapImage.CacheOption = BitmapCacheOption.OnLoad;

				bitmapImage.StreamSource = stream;
				bitmapImage.EndInit();
				bitmapImage.Freeze(); //以防万一你想在另一个线程中加载图像。

				double scale = Math.Round(bitmapImage.DpiX / 96d, 2);

				int x = Math.Min(bitmapImage.PixelWidth - 1, Math.Max(0, (int)(rect.X * scale)));
				int y = Math.Min(bitmapImage.PixelHeight - 1, Math.Max(0, (int)(rect.Y * scale)));
				int width = (int)(rect.Width * scale);
				int height = (int)(rect.Height * scale);

				width = Math.Min(width, bitmapImage.PixelWidth - x);
				height = Math.Min(height, bitmapImage.PixelHeight - y);

				rect = new Int32Rect(x, y, width, height);

				return !new Int32Rect(0, 0, bitmapImage.PixelWidth, bitmapImage.PixelHeight).Contains(rect)
					? null
					: (BitmapSource)new CroppedBitmap(bitmapImage, rect);
			}
		}



		public static string ToBase64(Bitmap bmp)
		{
			try
			{
				MemoryStream ms = new();
				bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
				byte[] arr = new byte[ms.Length];
				ms.Position = 0;
				ms.Read(arr, 0, (int)ms.Length);
				ms.Close();
				String strbaser64 = Convert.ToBase64String(arr);
				return strbaser64;
			}
			catch (Exception ex)
			{
				MessageBox.Show("ImgToBase64String 转换失败 Exception:" + ex.Message);
				return "";
			}
		}

		public static string BitmapSourceToBase64(BitmapSource bitmapSource)
		{
			using (MemoryStream memoryStream = new())
			{
				BitmapEncoder encoder = new PngBitmapEncoder(); // 可以根据需要选择其他编码器如JpegBitmapEncoder
				encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
				encoder.Save(memoryStream);

				byte[] bytes = memoryStream.ToArray();
				string base64String = Convert.ToBase64String(bytes);
				return base64String;
			}


		}




		public static BitmapSource CreateBitmapSourceFromBase64(string base64String)
		{
			byte[] bytes = DecodeBase64String(base64String);

			MemoryStream ms = new(bytes);
			ImageSourceConverter imageSourceConverter = new();
			ImageSource source = null;
			source = (ImageSource)imageSourceConverter.ConvertFrom(ms);
			return (BitmapSource)source;

		}
		public static byte[] DecodeBase64String(string base64String)
		{
			byte[] bytes = Convert.FromBase64String(base64String);
			return bytes;
		}


		public static BitmapImage BitmapToBitmapImage(System.Drawing.Bitmap bitmap)
		{
			BitmapImage bitmapImage = new();
			using (System.IO.MemoryStream ms = new())
			{
				bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
				bitmapImage.BeginInit();
				bitmapImage.StreamSource = ms;
				bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
				bitmapImage.EndInit();
				bitmapImage.Freeze();
			}
			return bitmapImage;
		}

		public static BitmapImage RenderTargetBitmapToBitmapImage(RenderTargetBitmap rtb)
		{
			RenderTargetBitmap renderTargetBitmap = rtb;
			BitmapImage bitmapImage = new();
			PngBitmapEncoder bitmapEncoder = new();
			bitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
			using (MemoryStream stream = new())
			{
				bitmapEncoder.Save(stream);
				stream.Seek(0, SeekOrigin.Begin);
				bitmapImage.BeginInit();
				bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
				bitmapImage.StreamSource = stream;
				bitmapImage.EndInit();
			}

			return bitmapImage;
		}

		public static void SaveBitmapSourceAsPNG(BitmapSource bitmapSource, string filePath, string ImgPath)
		{

			try
			{

				if (string.IsNullOrEmpty(filePath))
				{
					throw new ArgumentException("File path cannot be null or empty.", nameof(filePath));
				}
				if (!Directory.Exists(filePath))
				{
					Directory.CreateDirectory(filePath);
				}

				// 创建一个PngBitmapEncoder实例
				PngBitmapEncoder encoder = new();
				{
					// 将BitmapSource添加到编码器的帧中
					encoder.Frames.Add(BitmapFrame.Create(bitmapSource));


					// 将编码器写入到指定的文件路径
					using (FileStream stream = new(filePath, FileMode.Create))
					{
						encoder.Save(stream);
					}
				}

				Debug.WriteLine($"Bitmap source saved successfully to {filePath}");
			}
			catch (Exception ex)
			{
				Debug.WriteLine($"Error saving bitmap source: {ex.Message}");
			}
		}

		public static void SaveBitmapSourceAsPng(BitmapSource bitmapSource, string filePath)
		{
			try
			{


				// 确保文件路径有正确的扩展名
				if (!filePath.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
				{
					filePath += ".png";
				}

				// 创建一个Bitmap对象，这个对象需要在using语句中以确保资源被正确释放
				using (Bitmap bitmap = BitmapSourceToBitmap(bitmapSource))
				{
					// 保存Bitmap对象为PNG格式的文件
					bitmap.Save(filePath, ImageFormat.Png);
				}
			}
			catch (Exception ex)
			{
				LogWriter.Log(ex, "ImageExtensions.SaveBitmapSourceAsPng");
			}
		}


		private static Bitmap BitmapSourceToBitmap(BitmapSource source)
		{
			int width = source.PixelWidth;
			int height = source.PixelHeight;
			int stride = width * ((source.Format.BitsPerPixel + 7) / 8);
			byte[] pixels = new byte[stride * height];

			source.CopyPixels(pixels, stride, 0);

			Bitmap bitmap = new(width, height);

			// 锁定位图的位。
			BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height),
													  ImageLockMode.ReadWrite,
													  bitmap.PixelFormat);

			//将源像素复制到锁定的位图数据中
			System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bitmapData.Scan0, pixels.Length);

			//解锁这些位。
			bitmap.UnlockBits(bitmapData);

			return bitmap;
		}





	}
}
